package org.example.video.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.example.commons.common.Result;
import com.example.commons.entity.Comment;
import com.example.commons.entity.User;
import com.example.commons.entity.Video;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.example.video.client.BaseClient;
import org.example.video.service.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: authority-v3.0.7
 * @ClassName:VideoController
 * @description: VideoController前端控制器
 * @author:dyy
 * @Version 3.0
 **/

@Tag(name = "视频列表 前端控制器")
@RestController
@RequestMapping("/video")
public class VideoController {
    @Resource
    private VideoService videoService;

    @Resource
    private BaseClient  baseClient;

    @Resource
    private CommentService commentService;

    @Resource
    private VideoHistoryService historyService;

    @Resource
    private VideoRecommendService recommendService;

    @Resource
    private CollectService collectService;


    /**
     * 新增
     *
     * @param video
     * @return
     */
    @Operation(summary = "新增")
    @PostMapping
    public Result save(@RequestBody Video video) {
        video.setUid(StpUtil.getLoginIdAsLong());
        return Result.success(videoService.save(video));
    }


    /**
     * 修改
     *
     * @param video
     * @return
     */
    @Operation(summary = "修改")
    @PutMapping("/{id}")
    @Transactional
    public Result update(@PathVariable Long id, @RequestBody Video video) {
        // 获取原始视频状态
        Video originalVideo = videoService.getById(id);

        // 执行更新操作
        boolean updated = videoService.updateById(video);

        // 如果状态变为"未审核"，删除相关收藏
        if (updated && "未审核".equals(video.getStatu()) && !"未审核".equals(originalVideo.getStatu())) {
            collectService.removeByVideoId(video.getId());
        }

        return Result.success(updated);
    }


    /**
     * 查询所有Video
     *
     * @return
     */
    @Operation(summary = "查询所有Video")
    @GetMapping
    public Result findAll() {
        return Result.success(videoService.list());
    }


    /**
     * 获取单个
     *
     * @param id
     * @return
     */
    @Operation(summary = "获取单个")
    @GetMapping("/{id}")
    public Result findOne(@PathVariable Integer id) {
        return Result.success(videoService.getById(id));
    }


    /**
     * 用户分页显示
     *
     * @param
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Operation(summary = "用户分页显示")
    @GetMapping("/page")
    public Result findPage(
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "") Long uid,
            @RequestParam(defaultValue = "") String statu,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        LambdaQueryWrapper<Video> queryWrapper = buildQueryWrapper(name, uid, statu);
        // 添加用户专属过滤条件
        queryWrapper.eq(Video::getUid, StpUtil.getLoginIdAsLong());

        Page<Video> page = videoService.page(new Page<>(pageNum, pageSize), queryWrapper);
        return Result.success(processPageResult(page));
    }

    /**
     * 后端分页显示
     *
     * @param
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Operation(summary = "后端分页显示")
    @GetMapping("/back/page")
    public Result findBackPage(
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "") Long uid,
            @RequestParam(defaultValue = "") String statu,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        LambdaQueryWrapper<Video> queryWrapper = buildQueryWrapper(name, uid, statu);
        Page<Video> page = videoService.page(new Page<>(pageNum, pageSize), queryWrapper);
        return Result.success(processPageResult(page));
    }


    @Operation(summary = "分页显示")
    @GetMapping("/home")
    public Result findHome(
            @RequestParam(defaultValue = "") String name,
            @RequestParam(defaultValue = "0") Long uid,
            @RequestParam(defaultValue = "") String statu,
            @RequestParam(defaultValue = "") String tag,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(defaultValue = "") String sortField
    ) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(name)) {
            // name 不为空且不是空字符串的处理逻辑
            queryWrapper.like(Video::getName, name);
        }
        if (uid != null && uid != 0) {
            // name 不为空且不是空字符串的处理逻辑
            queryWrapper.eq(Video::getUid, uid);
        }
        if (StrUtil.isNotEmpty(tag)) {
            queryWrapper.like(Video::getTags, tag);
        }
        queryWrapper.eq(Video::getStatu,"已通过");

        switch (sortField) {
            case "click":
                queryWrapper.orderByDesc(Video::getClick);
                break;
            case "createTime":
                queryWrapper.orderByDesc(Video::getCreateTime);
                break;
            case "composite":
                queryWrapper.orderByDesc(Video::getClick);
                queryWrapper.orderByDesc(Video::getCreateTime);
                break;
            default:
                queryWrapper.orderByDesc(Video::getClick);
                queryWrapper.orderByDesc(Video::getCreateTime);
        }

        Page<Video> page = videoService.page(new Page<>(pageNum, pageSize), queryWrapper);
        List<Video> records = page.getRecords();
        for (Video video : records) {
            Integer commentCount = Math.toIntExact(commentService.count(new LambdaQueryWrapper<Comment>().eq(Comment::getVid, video.getId())));
            video.setCommentCount(commentCount);

            // 将 LinkedHashMap 转换为 JSON 字符串
            String json = JSONUtil.toJsonStr(baseClient.getUserById(video.getUid()));
            // 将 JSON 字符串反序列化为 User 对象
            User user = JSONUtil.toBean(json, User.class);
            if (ObjectUtil.isNotEmpty(user)) {
                video.setUser(user);
            }
        }

        if ("composite".equals(sortField)) {
            records.sort((v1, v2) -> {
                long score1 = v1.getClick() + v1.getCommentCount();
                long score2 = v2.getClick() + v2.getCommentCount();
                return Long.compare(score2, score1); // 降序排序
            });
        }

        page.setRecords(records);
        return Result.success(page);
    }


    @GetMapping("/byTag")
    public Result findByTag(
            @RequestParam String tag,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize
    ) {
        Page<Video> page = videoService.page(new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<Video>()
                        .like(Video::getTags, tag)
                        .eq(Video::getStatu, "已通过"));
        return Result.success(page);
    }


    @Operation(summary = "获取综合得分最高视频名称")
    @GetMapping("/topComposite")
    public Result getTopCompositeVideoName() {
        List<Video> videos = videoService.list(new LambdaQueryWrapper<Video>().eq(Video::getStatu, "已通过"));
        Video topVideo = null;
        double maxScore = 0;

        for (Video video : videos) {
            int commentCount = Math.toIntExact(commentService.count(
                    new LambdaQueryWrapper<Comment>().eq(Comment::getVid, video.getId())));
            double score = video.getClick() *0.4 + commentCount * 0.6;
            if (score > maxScore) {
                maxScore = score;
                topVideo = video;
            }
        }

        return Result.success(topVideo != null ? topVideo.getName() : "暂无热门视频");
    }


    /**
     * 单个删除
     *
     * @param id
     * @return
     */
    @Operation(summary = "单个删除")
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Long id) { // 改为 Long 类型
        return Result.success(videoService.removeVideoById(id));
    }


    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量删除")
    @DeleteMapping("/batch/{ids}")
    @Transactional
    public Result deleteByIds(@PathVariable String[] ids) {
        List<Long> idList = Arrays.stream(ids)
                .map(Long::parseLong)
                .collect(Collectors.toList());
        return Result.success(videoService.removeVideoByIds(idList));
    }


    /**
     * 批量导出
     * 使用的技术为alibaba下面的easyexcel
     * 写数据
     *
     * @param ids
     * @return
     */
    @Operation(summary = "批量导出")
    @GetMapping("/batch/export/{ids}")
    public void exportByIds(@PathVariable String[] ids, HttpServletResponse response) throws IOException {
        List<Video> list = videoService.listByIds(Arrays.asList(ids));
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("video导出数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Video.class).sheet("sheel1").doWrite(list);

    }


    /**
     * 批量导入
     * 使用的技术为alibaba下面的easyexcel
     * 读数据
     *
     * @param
     */
    @Operation(summary = "批量导入")
    @PostMapping("/batch/upload")
    public Result writeExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), Video.class, new PageReadListener<Video>(dataList -> {
            dataList.forEach(entity -> videoService.save(entity.toBuilder().id(null).build()));
        })).sheet().doRead();
        return Result.success();
    }


    /**
     * 增加识破点击数
     *
     * @param
     */
    @Operation(summary = "增加点击数")
    @PutMapping("/click/{id}")
    public Result incrementClick(@PathVariable Long id) {
        videoService.incrementClick(id);
        return Result.success();
    }


    /**
     * 获取最高播放量视频名称
     *
     * @param
     */
    @Operation(summary = "获取最高播放量视频名称")
    @GetMapping("/topVideoName")
    public Result getTopVideoName() {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Video::getClick);
        queryWrapper.last("LIMIT 1");
        Video video = videoService.getOne(queryWrapper);
        return Result.success(video != null ? video.getName() : "");
    }


    /**
     * 随机推荐视频
     *
     * @param
     */
    @Operation(summary = "获取随机推荐视频")
    @GetMapping("/random")
    public Result getRandomVideos() {
        QueryWrapper<Video> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("statu", "已通过")
                .orderByAsc("RAND()")
                .last("LIMIT 6");

        List<Video> videos = videoService.list(queryWrapper);

        // 关联用户信息
        List<Video> processedVideos = videos.stream().map(video -> {
            String json = JSONUtil.toJsonStr(baseClient.getUserById(video.getUid()));
            User user = JSONUtil.toBean(json, User.class);
            video.setUser(user);
            return video;
        }).collect(Collectors.toList());

        return Result.success(processedVideos);
    }


    /**
     * 记录浏览历史
     *
     * @param
     */
    @Operation(summary = "记录浏览历史")
    @PostMapping("/recordHistory/{videoId}")
    public Result recordHistory(@PathVariable Long videoId) {
        Long userId = StpUtil.getLoginIdAsLong();
        historyService.saveHistory(userId, videoId);
        return Result.success();
    }


    /**
     * 获取个性化推荐
     *
     * @param
     */
    @Operation(summary = "获取个性化推荐")
    @GetMapping("/personalRecommend")
    public Result getPersonalRecommend(@RequestParam(defaultValue = "0") Long _t) {
        Long userId = StpUtil.getLoginIdAsLong();
        List<Video> recommends = recommendService.recommendVideos(userId, _t);
        return Result.success(recommends);
    }


    private LambdaQueryWrapper<Video> buildQueryWrapper(String name, Long uid, String statu) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();

        // 公共过滤条件
        if (StrUtil.isNotEmpty(name)) {
            queryWrapper.like(Video::getName, name);
        }
        if (uid != null && uid != 0) {
            queryWrapper.eq(Video::getUid, uid);
        }
        if (StrUtil.isNotEmpty(statu)) {
            queryWrapper.like(Video::getStatu, statu);
        }

        // 角色权限过滤
        if (StpUtil.hasRole("user")) {
            queryWrapper.eq(Video::getUid, StpUtil.getLoginIdAsLong());
        }

        queryWrapper.orderByDesc(Video::getId);
        return queryWrapper;
    }

    private Page<Video> processPageResult(Page<Video> page) {
        List<Video> records = page.getRecords();
        for (Video video : records) {
            String json = JSONUtil.toJsonStr(baseClient.getUserById(video.getUid()));
            User user = JSONUtil.toBean(json, User.class);
            if (ObjectUtil.isNotEmpty(user)) {
                video.setUser(user);
            }
        }
        page.setRecords(records);
        return page;
    }
}